"""
tests for :mod:`pvlib.iotools.bsrn`
"""

import pandas as pd
import pytest
import os
import tempfile
from pvlib.iotools import read_bsrn, get_bsrn, parse_bsrn
from tests.conftest import (
    TESTS_DATA_DIR,
    RERUNS,
    RERUNS_DELAY,
    assert_index_equal,
    requires_bsrn_credentials,
)

from pvlib._deprecation import pvlibDeprecationWarning


@pytest.fixture(scope="module")
def bsrn_credentials():
    """Supplies the BSRN FTP credentials for testing purposes.

    Users should obtain their own credentials as described in the `read_bsrn`
    documentation."""
    bsrn_username = os.environ["BSRN_FTP_USERNAME"]
    bsrn_password = os.environ["BSRN_FTP_PASSWORD"]
    return bsrn_username, bsrn_password


@pytest.fixture
def expected_index():
    return pd.date_range(start='20160601', periods=43200, freq='1min',
                         tz='UTC')


def test_parse_bsrn_deprecated():
    with pytest.warns(pvlibDeprecationWarning, match='Use read_bsrn instead'):
        with open(TESTS_DATA_DIR / 'bsrn-lr0100-pay0616.dat') as fbuf:
            data, metadata = parse_bsrn(fbuf)


@pytest.mark.parametrize('testfile', [
    ('bsrn-pay0616.dat.gz'),
    ('bsrn-lr0100-pay0616.dat'),
])
def test_read_bsrn(testfile, expected_index):
    data, metadata = read_bsrn(TESTS_DATA_DIR / testfile)
    assert_index_equal(expected_index, data.index)
    assert 'ghi' in data.columns
    assert 'dni_std' in data.columns
    assert 'dhi_min' in data.columns
    assert 'lwd_max' in data.columns
    assert 'relative_humidity' in data.columns


def test_read_bsrn_buffer(expected_index):
    with open(TESTS_DATA_DIR / 'bsrn-lr0100-pay0616.dat') as fbuf:
        data, metadata = read_bsrn(fbuf)
    assert_index_equal(expected_index, data.index)
    assert 'ghi' in data.columns
    assert 'dni_std' in data.columns
    assert 'dhi_min' in data.columns
    assert 'lwd_max' in data.columns
    assert 'relative_humidity' in data.columns


def test_read_bsrn_logical_records(expected_index):
    # Test if logical records 0300 and 0500 are correct parsed
    # and that 0100 is not passed when not specified
    data, metadata = read_bsrn(TESTS_DATA_DIR / 'bsrn-pay0616.dat.gz',
                               logical_records=['0300', '0500'])
    assert_index_equal(expected_index, data.index)
    assert 'lwu' in data.columns
    assert 'uva_global' in data.columns
    assert 'uvb_reflected_std' in data.columns
    assert 'ghi' not in data.columns


def test_read_bsrn_bad_logical_record():
    # Test if ValueError is raised if an unsupported logical record is passed
    with pytest.raises(ValueError, match='not in'):
        read_bsrn(TESTS_DATA_DIR / 'bsrn-lr0100-pay0616.dat',
                  logical_records=['dummy'])


def test_read_bsrn_logical_records_not_found():
    # Test if an empty dataframe is returned if specified LRs are not present
    data, metadata = read_bsrn(TESTS_DATA_DIR / 'bsrn-lr0100-pay0616.dat',
                               logical_records=['0300', '0500'])
    assert data.empty  # assert that the dataframe is empty
    assert 'uva_global' in data.columns
    assert 'uvb_reflected_std' in data.columns
    assert 'uva_global_max' in data.columns
    assert 'dni' not in data.columns
    assert 'day' not in data.columns


@requires_bsrn_credentials
@pytest.mark.remote_data
@pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
def test_get_bsrn(expected_index, bsrn_credentials):
    # Retrieve irradiance data from the BSRN FTP server
    # the TAM station is chosen due to its small file sizes
    temp_dir = tempfile.TemporaryDirectory()  # create temporary directory
    username, password = bsrn_credentials
    data, metadata = get_bsrn(
        start=pd.Timestamp(2016, 6, 1),
        end=pd.Timestamp(2016, 6, 29),
        station='tam',
        username=username,
        password=password,
        save_path=temp_dir.name)
    assert_index_equal(expected_index, data.index)
    assert 'ghi' in data.columns
    assert 'dni_std' in data.columns
    assert 'dhi_min' in data.columns
    assert 'lwd_max' in data.columns
    assert 'relative_humidity' in data.columns
    # test that a local file was saved and is read correctly
    data2, metadata2 = read_bsrn(os.path.join(temp_dir.name, 'tam0616.dat.gz'))
    assert_index_equal(expected_index, data2.index)
    assert 'ghi' in data2.columns
    temp_dir.cleanup()  # explicitly remove temporary directory


@requires_bsrn_credentials
@pytest.mark.remote_data
@pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
def test_get_bsrn_bad_station(bsrn_credentials):
    # Test if KeyError is raised if a bad station name is passed
    username, password = bsrn_credentials
    with pytest.raises(KeyError, match='sub-directory does not exist'):
        get_bsrn(
            start=pd.Timestamp(2016, 6, 1),
            end=pd.Timestamp(2016, 6, 29),
            station='not_a_station_name',
            username=username,
            password=password)


@requires_bsrn_credentials
@pytest.mark.remote_data
@pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
def test_get_bsrn_no_files(bsrn_credentials):
    username, password = bsrn_credentials
    # Test if Warning is given if no files are found for the entire time frame
    with pytest.warns(UserWarning, match='No files'):
        get_bsrn(
            start=pd.Timestamp(1990, 6, 1),
            end=pd.Timestamp(1990, 6, 29),
            station='tam',
            username=username,
            password=password)
